package com.aspire.moss.portal.desktop;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Observable;
import java.util.Observer;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.ViewGroup.OnHierarchyChangeListener;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.Scroller;

import com.aspire.moss.portal.R;

public class Workspace extends ViewGroup implements OnHierarchyChangeListener, WorkspaceController {

    private static final String TAG = "Workspace";

    /**
     * workspace最多可以容纳的页数
     */
    public static final int MAX_PAGE = 10;

    private int screens; // 屏幕数

    private int mCurrentScreen;// 当前屏幕

    private boolean lock = false;

    /**
     * 当在屏幕移动大于多少时 翻页
     */
    private static int moveMin;

    private Context mContext;

    private Scroller mScroller;

    private VelocityTracker mVelocityTracker;

    private int lastx, downx, mTouchSlop;

    private WorkspaceListener workspaceListener;

    private WorkspaceAdapter workspaceAdapter;

    private WorkspaceAdapterObserver adapterObserver;

    private WorkspaceLock workspaceLock = new WorkspaceLock();
    /**
     * 删除应用的动画
     */
    private Animation delCellViewAnim;

    int mWidth, mTouthX, downX = 0;

    public Workspace(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public Workspace(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        mContext = context;
        // mScroller = new Scroller(mContext, AnimationUtils.loadInterpolator(
        // mContext, android.R.anim.accelerate_decelerate_interpolator));
        mScroller = new Scroller(mContext);
        this.setOnHierarchyChangeListener(this);
        adapterObserver = new WorkspaceAdapterObserver();
        final ViewConfiguration configuration = ViewConfiguration.get(context);
        mTouchSlop = configuration.getScaledTouchSlop();
        delCellViewAnim = AnimationUtils.loadAnimation(mContext, R.anim.scale);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        if (widthMode != MeasureSpec.EXACTLY) {
            throw new IllegalStateException("Workspace can only be used in EXACTLY mode.");
        }
        mWidth = MeasureSpec.getSize(widthMeasureSpec);
        moveMin = mWidth / 3;
        for (int i = 0; i < getChildCount(); i++) {
            getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec);
        }
        setMeasuredDimension(resolveSize(mWidth, widthMeasureSpec), resolveSize(MeasureSpec.getSize(heightMeasureSpec), heightMeasureSpec));
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int left = 0;
        View child = null;
        for (int i = 0; i < getChildCount(); i++) {
            child = getChildAt(i);
            child.layout(left, 0, left + child.getMeasuredWidth(), child.getMeasuredHeight());
            left += mWidth;
        }
    }

    @Override
    public void computeScroll() {
        super.computeScroll();
        Log.d(TAG, "mScroller.getCurrX()" + mScroller.getCurrX());
        if (mScroller.computeScrollOffset()) {
            scrollTo(mScroller.getCurrX(), 0);
            invalidate();
        }
    }

    @Override
    public void scrollTo(int x, int y) {
        mTouthX = x;
        super.scrollTo(x, y);
    }

    @Override
    public void scrollBy(int x) {
        scrollBy(x, 0);
        postInvalidate();
    }

    @Override
    public void scrollBy(int x, int y) {
        if ((getScrollX() <= 0 && Utils.isToRight(x)) || (getScrollX() >= (screens - 1) * mWidth && Utils.isToLeft(x))) {
            x /= 2;
        }
        super.scrollBy(x, y);
        mTouthX = getScrollX();
    }

    @Override
    public void scrollLeft() {
        Log.d(TAG, "scrollLeft");
        int target = 0;
        if (mCurrentScreen < screens - 1) {
            target = mCurrentScreen;
            target += 1;
        } else {
            target = mCurrentScreen;
        }
        scrollScreen(target);
    }

    @Override
    public void scrollRight() {
        Log.d(TAG, "scrollRight");
        int target = 0;
        if (mCurrentScreen != 0) {
            target = mCurrentScreen - 1;
        }
        scrollScreen(target);
    }

    /**
     * 动画移动屏幕
     * 
     * @param screent
     */
    public void scrollScreen(int screen) {
        Log.d(TAG, "scrollScreen = " + screen + "mCurrentScreen = " + mCurrentScreen);
        final int target = (screen * mWidth);
        mScroller.startScroll(mTouthX, 0, (target - mTouthX), 0, 250);
        postInvalidate();
        if (mCurrentScreen != screen) {
            mCurrentScreen = screen;
            if (null != workspaceListener) {
                workspaceListener.onSelectScreenChange(mCurrentScreen);
            }
        }
    }

    /**
     * 添加celllayout
     */
    private void loadCellLayout() {
        for (int i = 0; i < workspaceAdapter.getCount(); i++) {
            addCellLayout(i);
        }
    }

    private void addCellLayout(int page_no) {
        final CellLayout view = (CellLayout) workspaceAdapter.getGroupView(Workspace.this, page_no);
        if (view instanceof CellLayout) {
            view.page_no = page_no;
            addCelllayoutChild((CellLayout) view, page_no);
            addView(view, page_no);
        } else {
            Log.d(TAG, "add child view type is not Celllayou");
        }
    }

    /**
     * 添加celllayout子控件
     * 
     * @param cellLayout
     */
    private void addCelllayoutChild(CellLayout cellLayout, int group) {
        if (workspaceAdapter.getApps().size() <= group)
            return;
        List<AppInfo> apps = workspaceAdapter.getApps().get(group);
        if (null == apps)
            return;
        AppView child = null;
        for (int i = 0; i < apps.size(); i++) {
            child = workspaceAdapter.getChildView(group, i);
            addChildToCelllayout(cellLayout, child);
        }
    }

    /**
     * 子控件CellLayout添加AppView
     * 
     * @param cellLayout
     * @param child
     */
    private void addChildToCelllayout(CellLayout cellLayout, AppView child) {
        if (null == child || !(child instanceof AppView)) {
            throw new IllegalArgumentException("chidl type not is a cellview");
        }
        workspaceLock.addObserver((Observer) child);
        child.appInfo.page_no = cellLayout.page_no;// 设置它的屏幕id
        if (isLockWorkspace())
            child.update(null, lock);
        cellLayout.addView(child);
    }
    
    /**
     * 删除所有空的屏幕
     */
    private void removeEmptyScreens(){
        for(CellLayout layout : findEmptyScreen()){
            removeCelllayoutView(layout.page_no);
        }
    }

    @Override
    public int getCurrentScreen() {
        return mCurrentScreen;
    }

    public void resetScreen() {
        scrollScreen(mCurrentScreen);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        final int e = event.getAction();
        final int x = (int) event.getX();
        acquireVelocityTrackerAndAddMovement(event);
        switch (e) {
        case MotionEvent.ACTION_DOWN:
            Log.d(TAG, "MotionEvent.ACTION_DOWN x=" + x);
            downx = lastx = x;
            return true;
        case MotionEvent.ACTION_MOVE:
            Log.d(TAG, "MotionEvent.ACTION_MOVE x=" + x);
            int del = lastx - x;
            Log.d(TAG, "downx=" + downx + "del");
            lastx = x;
            scrollBy(del, 0);
            invalidate();
            break;
        case MotionEvent.ACTION_UP:
            Log.d(TAG, "MotionEvent.ACTION_UP x=" + x);
            mVelocityTracker.computeCurrentVelocity(1000);
            Log.d("TAG", "VelocityTracker =" + mVelocityTracker.getXVelocity());
            float xVelocity = mVelocityTracker.getXVelocity();
            if ((downx - x) > moveMin || (Math.abs(xVelocity) > Config.SNAP_VELOCITY && xVelocity < 0)) {
                scrollLeft();
            } else if ((downx - x) < 0 && Math.abs((downx - x)) > moveMin || (Math.abs(xVelocity) > Config.SNAP_VELOCITY && xVelocity > 0)) {
                scrollRight();
            } else {
                resetScreen();
            }
            downx = 0;
            releaseVelocityTracker();
        case MotionEvent.ACTION_CANCEL:
            Log.d(TAG, "MotionEvent.ACTION_CANCEL x=" + x);
            resetScreen();
            break;
        default:
            break;
        }
        return true;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        Log.d(TAG, "onInterceptTouchEvent ev= " + ev);
        boolean con = false;
        final int e = ev.getAction();
        final int x = (int) ev.getX();
        switch (e) {
        case MotionEvent.ACTION_UP:
            break;
        case MotionEvent.ACTION_DOWN:
            acquireVelocityTrackerAndAddMovement(ev);
            downx = lastx = x;
            return false;
        case MotionEvent.ACTION_MOVE:
            int diff = Math.abs(x - lastx);
            if (diff / 2 > mTouchSlop) {
                con = true;
            }
            Log.d(TAG, "con = " + con + "  diff=" + diff);
            return con;
        }
        return false;
    }

    private void acquireVelocityTrackerAndAddMovement(MotionEvent ev) {
        if (mVelocityTracker == null) {
            mVelocityTracker = VelocityTracker.obtain();
        }
        mVelocityTracker.addMovement(ev);
    }

    private void releaseVelocityTracker() {
        if (mVelocityTracker != null) {
            mVelocityTracker.recycle();
            mVelocityTracker = null;
        }
    }

    public void setWorkspaceListener(WorkspaceListener workspaceListener) {
        this.workspaceListener = workspaceListener;
    }

    /**
     * 当添加一个页时,设置WorkspaceListener
     */
    @Override
    public void onChildViewAdded(View parent, View child) {
        Log.d(TAG, "onChildViewAdded childs size=" + getChildCount());
        if (null != workspaceListener) {
            screens = getChildCount();
            workspaceListener.onScreenCountChange(screens);
        }
    }

    /**
     * 当删除一个页时,设置WorkspaceListener
     */
    @Override
    public void onChildViewRemoved(View parent, View child) {
        Log.d(TAG, "onChildViewRemoved childs size=" + getChildCount());
        if (null != workspaceListener) {
            
            screens = getChildCount();
            workspaceListener.onScreenCountChange(screens);
        }
    }

    public void setWorkspaceAdapter(WorkspaceAdapter workspaceAdapter) {
        if (null != workspaceAdapter) {
            this.workspaceAdapter = workspaceAdapter;
            this.workspaceAdapter.addObserver(adapterObserver);
        }
    }

    @Override
    public void lockWorkspace() {
        if (!lock) {
            lock = true;
            workspaceLock.onChange(lock);
        }
    }

    @Override
    public void unlockWorkspace() {
        if (lock) {
            lock = false;
            workspaceLock.onChange(lock);
            resetWorkspace();
        }
    }

    @Override
    public boolean isLockWorkspace() {
        return lock;
    }

    @Override
    public int getScreens() {
        return screens;
    }

    @Override
    public void addAppView(AppInfo appInfo) {
        List<AppInfo> group = workspaceAdapter.getGroup(appInfo.page_no);
        if (null != group) {
            group.add(appInfo);
            AppView child = workspaceAdapter.getChildView(appInfo.page_no, group.indexOf(appInfo));
            CellLayout cellLayout = findScreen(appInfo.page_no);
            addChildToCelllayout(cellLayout, child);
        }
    }

    @Override
    public void addNewAppView(AppInfo appInfo) {
        // TODO
    }

    @Override
    public void addCelllayoutView() {
        int screenId = getChildCount();
        addCellLayout(screenId);
        workspaceAdapter.addGroupView(screenId);
    }
    
    @Override
    public boolean removeCelllayoutView(int page_no) {
        CellLayout layout = null;
        for(int i = 0 ; i < getChildCount() ; i ++){
            layout = (CellLayout) getChildAt(i);
            if(null != layout && layout.page_no == page_no){
                removeView(layout);
                break;
            }
        }
        return true;
    }

    @Override
    public CellLayout findScreen(int page_no) {
        CellLayout temp = null;
        for (int i = 0; i < getChildCount(); i++) {
            temp = (CellLayout) getChildAt(i);
            if (temp.page_no == page_no)
                break;
        }
        return temp;
    }

    @Override
    public boolean removeAppView(AppInfo appInfo, int visible) {
        return removeAppView(appInfo, true, visible);
    }

    @Override
    public ArrayList<CellLayout> findEmptyScreen() {
        CellLayout cellLayout = null;
        final ArrayList<CellLayout> emptyCellLayouts = new ArrayList<CellLayout>();
        for (int i = 0; i < getChildCount(); i++) {
            cellLayout = findScreen(i);
            if (null != cellLayout && cellLayout.isEmpty()) {
                emptyCellLayouts.add(cellLayout);
            }
        }
        return emptyCellLayouts;
    }

    @Override
    public void resetWorkspace() {
        removeEmptyScreens();
        int [] sortScreens = sortScreens(findScreens());
        CellLayout cellLayout = null;
        for(int i = 0 ; i < sortScreens.length ; i ++){
            cellLayout = findScreen(sortScreens[i]);
            if(null != cellLayout){
                cellLayout.onPageNoChange(i);
            }
        }
        scrollScreen(0);
    }
    
    private int [] sortScreens(int [] arrayScreens){
        for(int i = 0 ; i < arrayScreens.length - 1 ; i ++){
            for(int j = 0 ; j < arrayScreens.length - 1 - i ; j ++){
                if(arrayScreens[j] > arrayScreens[j + 1]){
                    int temp = 0;
                    temp = arrayScreens[j];
                    arrayScreens[j] = arrayScreens[j + 1];
                    arrayScreens[j + 1] = temp;
                }
            }
        }
        return arrayScreens;
    }
    
    private int [] findScreens(){
        final int [] arrayScreens = new int [getChildCount()];
        CellLayout layout = null;
        for(int i = 0 ; i < getChildCount() ; i ++){
            layout = (CellLayout) getChildAt(i);
            arrayScreens[i] = layout.page_no;
        }
        return arrayScreens;
    }

    private boolean removeAppView(AppInfo appInfo, boolean isAnim, int visible) {
        boolean con = false;
        if (null != appInfo) {
            final int screenId = appInfo.page_no;
            final CellLayout cellLayout = findScreen(screenId);
            if (isAnim) {
                con = cellLayout.removeAppView(appInfo, delCellViewAnim, visible);
            } else {
                con = cellLayout.removeAppView(appInfo, null, visible);
            }

        }
        if (con) {
            workspaceAdapter.removeAppInfo(appInfo);// 如果删除应用的视图成功,删除workspaceAdapter里的数据
        }
        return con;
    }

    @Override
    public boolean moveAppView(AppInfo appInfo, AppInfo target) {
        final CellLayout ceLayout = findScreen(target.page_no);
        if (null != ceLayout) {
            if (appInfo.eqPosScreen(target)) {// 不需要移动
            // ceLayout.findAppView(target , GONE).setVisibility(VISIBLE);
            } else if (appInfo.page_no == target.page_no) {
                // final AppView cellView = (AppView)
                // ceLayout.findAppView(appInfo,GONE);
                // ceLayout.moveToXY(cellView, target.cellX, target.cellY,
                // false);
                // cellView.setVisibility(VISIBLE);
            } else {
                addAppView(target);
                removeAppView(appInfo, false, GONE);
            }
        } else {
            return false;
        }

        return true;
    }

    @Override
    public boolean swapAppView(AppInfo appInfo, AppInfo target) {
        // final CellLayout ceLayout = findScreen(target.page_no);
        // if (appInfo.page_no == target.page_no) { //
        // 在当前页面进行移动,取得目标对的信息,如果目标存,则是交换位置,如果没有则是老自己移动到最一个
        // final AppView cellView = (AppView)
        // ceLayout.findAppView(appInfo,GONE);
        // ceLayout.moveToXY(cellView, target.cellX, target.cellY, false);
        // cellView.setVisibility(VISIBLE);
        // }else{
        // //这里是不同页面之间的交换
        // //TODO
        // final AppInfo targetChange = appInfo.cloneAppInfo();
        // targetChange.screen = target.screen;
        // targetChange.cellX = target.cellX;
        // targetChange.cellY = target.cellY;
        //
        // final AppInfo appInfoChange = target.cloneAppInfo();
        // appInfoChange.page_no = appInfo.page_no;
        // appInfoChange.cellX = appInfo.cellX;
        // appInfoChange.cellY = appInfo.cellY;
        //
        // ((AppView)
        // findScreen(appInfo.screen).findAppView(appInfo,GONE)).change(appInfoChange,
        // View.VISIBLE);
        // ((AppView)
        // findScreen(target.screen).findAppView(target,VISIBLE)).change(targetChange);
        // }
        return true;
    }

    @Override
    public boolean resetAppView(AppInfo appInfo) {
        final CellLayout ceLayout = findScreen(appInfo.page_no);
        // View view = ceLayout.findAppView(appInfo, GONE);
        // if(view.getVisibility() == GONE){
        // view.setVisibility(VISIBLE);
        // }
        return true;
    }

    /**
     * 当工作空间的信息发生改变化时
     * 
     * @author Administrator
     * 
     */
    public interface WorkspaceListener {
        /**
         * 当选中的屏幕发生变化时
         * 
         * @param mCurrentScreen
         */
        void onSelectScreenChange(int mCurrentScreen);

        /**
         * 当屏幕数发生变化时
         * 
         * @param count
         */
        void onScreenCountChange(int count);
    }

    /**
     * 用于监听数据适配器的变化
     * 
     * @author Administrator
     */
    private final class WorkspaceAdapterObserver implements Observer {

        @Override
        public void update(Observable observable, Object data) {
            /**
             * 当数据适配器发生变化时,重新把界面刷新
             */
            if (observable instanceof WorkspaceAdapter) {
                removeAllViews();
                loadCellLayout();
            }
        }

    }

    /**
     * 观察者模式,当worksapce锁定时
     * 
     * @author Administrator
     * 
     */
    private final class WorkspaceLock extends Observable {

        public void onChange(boolean con) {
            setChanged();
            notifyObservers(con);
        }

    }

    public void printInfo() {
        // TODO Auto-generated method stub

    }

}
